#include <stdexcept>

struct Point3D
	{
	double m_x, m_y, m_z;

	bool operator==(const Point3D& i_right) const
		{
		return(m_x == i_right.m_x && m_y == i_right.m_y && m_z == i_right.m_z);
		}

	double operator[](size_t i_pos) const
		{
		switch (i_pos)
			{
			case 0:
				return m_x;
			case 1:
				return m_y;
			case 2:
				return m_z;
			default:
				throw(std::out_of_range("Invalid index"));
			}
		}
	};

struct Triangle3D
	{
	Point3D m_a, m_b, m_c;
	};

Point3D CrossProduct(const Point3D& i_a, const Point3D& i_b);
double DotProduct(const Point3D& i_a, const Point3D& i_b);
Point3D Substitute(const Point3D& i_a, const Point3D& i_b);
double Abs(const Point3D& i_point);
void SortPair(std::pair<double, double>& io_pair);
double LessThanEpsilon(double i_number);

bool PointInsideTriangle(const Triangle3D& i_triangle, const Point3D& i_point);

bool ComputeIntervals(
	double& o_a, double& o_b, double& o_c, double& o_x0, double& o_x1,
	double i_p0, double i_p1, double i_p2, double i_d0, double i_d1, double i_d2);
bool EdgeAgainstEdge(const Point3D& i_point, const Point3D& i_edge_start, const Point3D& i_edge_finish,
	size_t i_i0, size_t i_i1, double i_a_x, double i_a_y);
bool EdgeAgainstTriangle(const Point3D& i_first, const Point3D& i_second, const Triangle3D& i_triangle,
	size_t i_i0, size_t i_i1);
bool HandleCoplanarTriangles(const Point3D& i_n, const Triangle3D& i_first, const Triangle3D& i_second);

bool AreTrianglesIntersecting(const Triangle3D& i_a, const Triangle3D& i_b);